package com.ibm.ops.domain.report;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

import com.ibm.ops.domain.metadata.OpsAuditLogReportMetaData;

public abstract class OpsAuditLogReport {

	protected HashMap<OpsAuditLogReportMetaDataKey,List<OpsAuditLogReportMetaData>> report = null;
	
	protected int indexCounter = 0;
	
	protected OpsAuditLogReportMetaData currentMetaData = null;
	
	public OpsAuditLogReport(){
		this.report = new HashMap<OpsAuditLogReportMetaDataKey,List<OpsAuditLogReportMetaData>>();
	}
	
	public void addReportData(String metaData){
		if(this.report != null && metaData.length() > 0){			
			OpsAuditLogReportMetaData metaDataObj = this.constructOpsAuditLogReportMetaData(metaData);
			OpsAuditLogReportMetaDataKey keyObj = this.retrieveOpsAuditLogReportMetaDataKey(metaData);
			
			if(this.report.containsKey(keyObj)){
				this.report.get(keyObj).add(metaDataObj);
			}else{
				keyObj.index = ++indexCounter;
				List<OpsAuditLogReportMetaData> domain = new ArrayList<OpsAuditLogReportMetaData>();
				domain.add(metaDataObj);
				this.report.put(keyObj,domain);
			}
//			System.out.println(this.report);
		}
	}
	
	protected abstract OpsAuditLogReportMetaData constructOpsAuditLogReportMetaData(String metaData);
	protected abstract OpsAuditLogReportMetaDataKey retrieveOpsAuditLogReportMetaDataKey(String metaData);
	
	public List<OpsAuditLogReportMetaData> constructReportFormat(){
		if(this.report != null){
			List<OpsAuditLogReportMetaData> result = new ArrayList<OpsAuditLogReportMetaData>();
			Set<OpsAuditLogReportMetaDataKey> keySet = this.report.keySet();
			List<OpsAuditLogReportMetaDataKey> keyList = new ArrayList<OpsAuditLogReportMetaDataKey>(keySet);
			Collections.sort(keyList);
			int count = keyList.size();
			for(int i = 0; i < count; i++){
				List<OpsAuditLogReportMetaData> domains = this.report.get(keyList.get(i));
				if(domains.size() > 0){
					domains.get(0).setCount((domains.size() + ""));
				}
				result.add(domains.get(0));
			}
			return result;
		}
		return null;
	}
	
	protected String retrieveData(String metaData,int startIX, int endIX){
		return metaData.substring(startIX, endIX).trim();
	}
	
	static class OpsAuditLogReportMetaDataKey implements Comparable<OpsAuditLogReportMetaDataKey>{
		private int index = 0;
		private String key = "";
		
		OpsAuditLogReportMetaDataKey(String key){
			this.key = key;
		}
//		@Override
		public int compareTo(OpsAuditLogReportMetaDataKey o) {
			return this.index - o.index;
		}
		@Override
		public int hashCode() {
			return new HashCodeBuilder(17, 37).
				       append(this.key).
				       toHashCode();
		}
		@Override
		public boolean equals(Object obj) {
		   if (obj == null) { return false; }
		   if (obj == this) { return true; }
		   if (obj.getClass() != getClass()) {
		     return false;
		   }
		   OpsAuditLogReportMetaDataKey key = (OpsAuditLogReportMetaDataKey) obj;
		   return new EqualsBuilder()
		                 .append(this.key, key.key)
		                 .isEquals();
		 }
		@Override
		public String toString() {
			return this.key;
		} 			
	}
}
